#[cfg(windows)]
pub mod win10;

use hbb_common::{bail, lazy_static, ResultType};
use std::{path::Path, sync::Mutex};

lazy_static::lazy_static! {
    // If device is uninstalled though "Device Manager" Window.
    // Rustdesk is unable to handle device any more...
    static ref H_SW_DEVICE: Mutex<u64> = Mutex::new(0);
    static ref MONITOR_PLUGIN: Mutex<Vec<u32>> = Mutex::new(Vec::new());
}

pub fn download_driver() -> ResultType<()> {
    // #[cfg(windows)]
    // let _download_url = win10::DRIVER_DOWNLOAD_URL;
    #[cfg(target_os = "linux")]
    let _download_url = "";

    // process download and report progress

    Ok(())
}

pub fn install_update_driver(_reboot_required: &mut bool) -> ResultType<()> {
    // #[cfg(windows)]
    // let install_path = win10::DRIVER_INSTALL_PATH;
    // #[cfg(not(windows))]
    let install_path = "";

    let abs_path = Path::new(install_path).canonicalize()?;
    if !abs_path.exists() {
        bail!("{} not exists", install_path)
    }

    // #[cfg(windows)]
    // unsafe {
    //     {
    //         // Device must be created before install driver.
    //         // https://github.com/fufesou/RustDeskIddDriver/issues/1
    //         if let Err(e) = create_device() {
    //             bail!("{}", e);
    //         }

    //         let full_install_path: Vec<u16> = abs_path
    //             .to_string_lossy()
    //             .as_ref()
    //             .encode_utf16()
    //             .chain(Some(0).into_iter())
    //             .collect();

    //         let mut reboot_required_tmp = win10::idd::FALSE;
    //         if win10::idd::InstallUpdate(full_install_path.as_ptr() as _, &mut reboot_required_tmp)
    //             == win10::idd::FALSE
    //         {
    //             bail!("{}", win10::get_last_msg()?);
    //         }
    //         *_reboot_required = reboot_required_tmp == win10::idd::TRUE;
    //     }
    // }

    Ok(())
}

pub fn uninstall_driver(_reboot_required: &mut bool) -> ResultType<()> {
    // #[cfg(windows)]
    // let install_path = win10::DRIVER_INSTALL_PATH;
    // #[cfg(not(windows))]
    let install_path = "";

    let abs_path = Path::new(install_path).canonicalize()?;
    if !abs_path.exists() {
        bail!("{} not exists", install_path)
    }

    // #[cfg(windows)]
    // unsafe {
    //     {
    //         let full_install_path: Vec<u16> = abs_path
    //             .to_string_lossy()
    //             .as_ref()
    //             .encode_utf16()
    //             .chain(Some(0).into_iter())
    //             .collect();

    //         let mut reboot_required_tmp = win10::idd::FALSE;
    //         if win10::idd::Uninstall(full_install_path.as_ptr() as _, &mut reboot_required_tmp)
    //             == win10::idd::FALSE
    //         {
    //             bail!("{}", win10::get_last_msg()?);
    //         }
    //         *_reboot_required = reboot_required_tmp == win10::idd::TRUE;
    //     }
    // }

    Ok(())
}

pub fn is_device_created() -> bool {
    // #[cfg(windows)]
    // return *H_SW_DEVICE.lock().unwrap() != 0;
    // #[cfg(not(windows))]
    return false;
}

pub fn create_device() -> ResultType<()> {
    if is_device_created() {
        return Ok(());
    }
    // #[cfg(windows)]
    // unsafe {
    //     let mut lock_device = H_SW_DEVICE.lock().unwrap();
    //     let mut h_sw_device = *lock_device as win10::idd::HSWDEVICE;
    //     if win10::idd::DeviceCreate(&mut h_sw_device) == win10::idd::FALSE {
    //         bail!("{}", win10::get_last_msg()?);
    //     } else {
    //         *lock_device = h_sw_device as u64;
    //     }
    // }
    Ok(())
}

pub fn close_device() {
    // #[cfg(windows)]
    // unsafe {
    //     win10::idd::DeviceClose(*H_SW_DEVICE.lock().unwrap() as win10::idd::HSWDEVICE);
    //     *H_SW_DEVICE.lock().unwrap() = 0;
    //     MONITOR_PLUGIN.lock().unwrap().clear();
    // }
}

pub fn plug_in_monitor() -> ResultType<()> {
    // #[cfg(windows)]
    // unsafe {
    //     let monitor_index = 0 as u32;
    //     let mut plug_in_monitors = MONITOR_PLUGIN.lock().unwrap();
    //     for i in 0..plug_in_monitors.len() {
    //         if let Some(d) = plug_in_monitors.get(i) {
    //             if *d == monitor_index {
    //                 return Ok(());
    //             }
    //         };
    //     }
    //     if win10::idd::MonitorPlugIn(monitor_index, 0, 30) == win10::idd::FALSE {
    //         bail!("{}", win10::get_last_msg()?);
    //     }
    //     (*plug_in_monitors).push(monitor_index);
    // }
    Ok(())
}

pub fn plug_out_monitor() -> ResultType<()> {
    // #[cfg(windows)]
    // unsafe {
    //     let monitor_index = 0 as u32;
    //     if win10::idd::MonitorPlugOut(monitor_index) == win10::idd::FALSE {
    //         bail!("{}", win10::get_last_msg()?);
    //     }
    //     let mut plug_in_monitors = MONITOR_PLUGIN.lock().unwrap();
    //     for i in 0..plug_in_monitors.len() {
    //         if let Some(d) = plug_in_monitors.get(i) {
    //             if *d == monitor_index {
    //                 plug_in_monitors.remove(i);
    //                 break;
    //             }
    //         };
    //     }
    // }
    Ok(())
}

pub fn update_monitor_modes() -> ResultType<()> {
    // #[cfg(windows)]
    // unsafe {
    //     let monitor_index = 0 as u32;
    //     let mut modes = vec![win10::idd::MonitorMode {
    //         width: 1920,
    //         height: 1080,
    //         sync: 60,
    //     }];
    //     if win10::idd::FALSE
    //         == win10::idd::MonitorModesUpdate(
    //             monitor_index as win10::idd::UINT,
    //             modes.len() as win10::idd::UINT,
    //             modes.as_mut_ptr(),
    //         )
    //     {
    //         bail!("{}", win10::get_last_msg()?);
    //     }
    // }
    Ok(())
}
